## Auth Redirection

URL redirections are often about protecting URLs from unauthenticated users:
if a user is not authenticated and goes to `/admin` then we redirect the user to `/login`.

Instead of doing a URL redirection, we can use a Route Function instead:

```js
// admin.page.route.js

export const '/admin'
```

```js
// login.page.route.js

export default pageContext => {
  const userIsAuthenticated =  pageContext.user !== null
  // If the user is authenticated and goes to `/admin`, then we render the Admin Panel
  if (userIsAuthenticated) {
    return false
  }
  // If the user is not authenticated and goes to `/admin`, then we render the Login Page
  return {
    // We override the Route String `/admin` of `admin.page.route.js`.
    // (Route Strings have a `precedence` value of `0`.)
    precedence: 1
  }
}
```

After the user has successfully completed the Login Form rendered at `/admin`,
we can do a `window.location.reload()` and `/admin` will now render the Admin Panel.
This means that the user always stays on `/admin` during the entire authentication flow.

However, we can still perform a page redirection if we want. See sections below.

## Server-side

We can perform a URL redirection by using `pageContext`:

```js
// _default.page.server.js

export function render() {
  if (someCondition) {
    return {
      documentHtml: null,
      pageContext: {
        redirectTo: '/some/url'
      }
    }
  }

  // The usual stuff
  // ...
}
```
```js
// server.js

const renderPage = createPageRenderer(/*...*/)
app.get('*', async (req, res, next) => {
  const pageContextInit = { url: req.url }
  const pageContext = await renderPage(pageContextInit)
  if (pageContext.redirectTo) {
    res.redirect(307, '/movie/add')
  } else if (!pageContext.httpResponse) {
    return next()
  } else {
    const { body, statusCode, contentType } = pageContext.httpResponse
    res.status(statusCode).type(contentType).send(body)
  }
})
```

We can also trigger a page redirection from a page:

```js
// movie.page.route.js
export default "/star-wars/:movieId"
```
```js
// movie.page.server.js

export { onBeforeRender }

async function onBeforeRender(pageContext) {
  const movie = await fetchMovie(pageContext.routeParams.movieId)
  // If the user goes to `/movie/42` but there is no movie with ID `42` then
  // we redirect the user to `/movie/add` so he can add a new movie.
  if (movie === null) {
    return {
      pageContext: {
        redirectTo: '/movie/add'
      }
    }
  }
}
```
```js
// _default.page.server.js

export { render }

function render(pageContext) {
  const { redirectTo } = pageContext
  if (redirectTo) {
    return {
      pageContext: {
        redirectTo
      }
    }
  }

  // The usual stuff
  // ...
}
```

## Client-side

If we use Client Routing, then we can also redirect on the client-side.

```js
// _default.page.server.js
// Environment: Node.js

// We make `pageContext.redirectTo` available to the browser for client-side redirection
export const passToClient = [/*...*/, 'redirectTo']
```
```js
// _default.page.client.js
// Environment: Browser

import { useClientRouter, navigate } from 'vite-plugin-ssr/client/router'

useClientRouter({
  render(pageContext) {
    const { redirectTo } = pageContext
    if (redirectTo) {
      navigate(redirectTo)
      return
    }

    // The usual stuff
    // ...
  }
})
```

## Hydration Mismatch

If we use Client Routing we may end up with a [hydration mismatch](/hydration-mismatch).

To remove the hydration mismatch, we may need to redirect on both the client-side and server-side.

There are situations when server-side redirection is not an option and we can only redirect on the client-side. In such case we can [suppress the hydration mismatch warning](/hydration-mismatch#suppress-hydration-mismatch). Alternatively, we can also first hydrate the original page (before redirecting) and then redirect and render the new page.
